<?php
include_once("config.php");

$prem = '';
$defaultUserTable = false;
// $method 可以为 openssl_get_cipher_methods() 返回的方式
function enAes($data, $AesData = defAesOpt, $option = 0)
{
  $res = openssl_encrypt(json_encode($data), $AesData['method'], $AesData['key'], $option, $AesData['iv']);
  return $res;
}
function deAes($data, $AesData = defAesOpt, $option = 0)
{
  if (is_string($data) || is_numeric($data)) {
    // return $data;
    $res = openssl_decrypt($data, $AesData['method'], $AesData['key'], $option, $AesData['iv']);
    return json_decode($res, true);
  }
}
function getToken($cmd, $table = 'users', $keyList = ['type'], $AesData = defAesOpt)
{
  if (is_array($cmd) && is_array($keyList) && isset($cmd['username']) && isset($cmd['password'])) {
    $ret = GetData(['table' => $table, 'username' => $cmd['username'], 'password' => $cmd['password']], 'id,username,password,' . join($keyList, ','));
    if (!$ret['error']) {
      $ret = $ret[0];
      $ret['uniqid'] = uniqid();
      $ret = ['token' => enAes($ret, $AesData)];
      return $ret;
    }
  }
}
function Token2user($cmd, $table = 'users', $AesData = defAesOpt)
{
  if (is_array($cmd) && isset($cmd['token'])) {
    $ret = deAes($cmd['token'], $AesData);
    if (is_array($ret) && $ret['TokenOvertime'] > time()) {
      $ret = GetData(['table' => $table, 'id' => $ret['id']]);
      if (is_array($ret) && count($ret) > 0) return $ret[0];
    }
  }
}
function useToken(&$cmd, $table = 'users', $AesData = defAesOpt)
{
  if (is_array($cmd) && isset($cmd['token'])) {
    $ret = deAes($cmd['token'], $AesData);
    $ret = GetData(['table' => $table, 'id' => $ret['id'], 'username' => $ret['username'], 'password' => $ret['password']]);
    // unset($cmd['token']);
    if ($ret) {
      $ret = $ret[0];
      UpData(['table' => $table, 'useTime' => time(), 'where' => ['id' => $ret['id']]]);
      unset($ret['password']);
      return $ret;
    }
  }
}
function ConnectSql()
{
  global $con, $Username, $Password, $ServerName, $TableName;
  if ($con == null) $con = mysqli_connect($ServerName, $Username, $Password, $TableName);
  mysqli_options($con, MYSQLI_OPT_INT_AND_FLOAT_NATIVE, true);
}
ConnectSql();
function CloseSQL()
{
  global $con;
  mysqli_close($con);
  $con = null;
}
function getRule($val)
{
  if (is_string($val)) {
    $str1 = substr($val, 0, 1);
    if (substr($val, 0, 2) == '!=') {
      return 2;
    } elseif (
      $str1 == '>' ||
      $str1 == '<' ||
      $str1 == '='
    ) {
      return 1;
    } elseif (substr($val, 0, 6) == ' like ') {
      return 6;
    } elseif (substr($val, 0, 4) == ' in(') {
      return strlen($val);
    } elseif (substr($val, 0, 8) == ' REGEXP ') {
      return 8;
    }
  }
  return 0;
}
function formatMysql($val)
{
  if (!$val) $val = 0;
  $val = str_replace("\\", "\\\\", $val);
  $val =  str_replace("'", "\'", $val);
  if (substr($val, 0, 6) == ' like ') $val = " like '" . substr($val, 5) . "'";
  return $val;
}
function isNumber($key, $val = false)
{
  $array = [ // $ret = ' ;
    'id', '价格', 'weight', '浏览量', '权限', '类型', '余额', '上级ID', '推荐ID',
    '归属用户', '商品类型', '服务承诺', '预订须知', '车型', '人数', '金额', '到账',
    '商品ID', '归属商家', '归属客户', '评价打分', 'node', 'state', 'cid'
  ];
  $ret = in_array($key, $array);
  if (!$ret && $val) {
    $len = strlen($key);
    // $rule = ['+','-','*','/'];
    if (substr($val, 0, $len) === $key) $ret = true;
  }
  return $ret;
}
function strIn($str, $in)
{
  if (is_string($in)) $in = [$in];
  $num = count($in);
  for ($i = 0; $i < $num; $i++) {
    if (!(stripos($str, $in[$i]) === false)) return $in[$i];
  }
  return false;
}
define('IntKey', ['id', 'cid', 'pid', 'state', 'type']);
define('SqlCmd', [';', '\n', 'from', 'where', 'update', 'del', 'insert', 'select']);
define('Logic', [
  '>', '<', '=', '!=',
  'REGEXP BINARY ',
  'REGEXP ',
  'IN ',
  'LIKE '
]);
function replaceSQL($ret)
{
  if (substr($ret, 0, 1) == '\'' && substr($ret, -1) == '\'') {
    $ret = substr($ret, 1, strlen($ret) - 2);
  }
  $ret = str_replace("\\", "\\\\", $ret);
  $ret =  str_replace("'", "\'", $ret);
  return $ret;
};
function setVal($key, $val, $cat = false, $debug = false)
{
  $ret = false;
  $logic = '=';
  if (is_numeric($val)) {
    $ret = "$key=$val";
  } elseif (is_array($val)) {
    $t = true;
    foreach ($val as $v) {
      if (!is_numeric($v)) $t = false;
    }
    if ($val)
      $ret = $t ? "$key in(" . implode(',', $val) . ')' : "$key in('" . implode('\',\'', $val) . '\')';
    else $ret = '';
  } else {
    if ($cat) return "$key$val";
    while (substr($val, 0, 1) == ' ') {
      $val = substr($val, 1);
    }
    foreach (Logic as $v) {
      $l = strlen($v);
      $logic = strtoupper(substr($val, 0, $l));
      if ($logic == $v) {
        $ret = substr($val, $l);
        break;
      }
    }
    if ($ret) {
      if (is_numeric($ret)) {
        $ret = $key . $logic . $ret;
      } else {
        if (substr($ret, 0, 1) == '(' && substr($ret, -1) == ')') {
          $ret = explode(',', substr($ret, 1, strlen($ret) - 2));
          $t = true;
          foreach ($ret as $i => $v) {
            $ret[$i] = replaceSQL($v);
            if ($t && !is_numeric($v)) {
              $t = false;
            }
          }
          $ret = $t ?  '(' . implode(',', $ret) . ')' : '(\'' . implode('\',\'', $ret) . '\')';
          $ret = $key . $logic . $ret;
        } else {
          $ret = "$key $logic'" . replaceSQL($ret) . '\'';
        }
      }
    } else $ret = "$key='" . replaceSQL($val) . '\'';
  }
  return $ret;
};
function formatWhere($cmd, $logic = 'and')
{
  if (!$cmd || !is_array($cmd)) return '';
  $logic = ' ' . $logic . ' ';
  $ret = [];
  $tmp = ['weight', 'limit'];
  foreach ($cmd as $k => $v) {
    if (in_array($k, $tmp)) continue;
    $v = setVal($k, $v);
    if ($v) $ret[] = $v;
    // $ret[] = $k;
  }
  if ($ret) $ret = implode($logic, $ret);
  else $ret = 'true';
  $ret = ' where ' . $ret;
  // mPrintX($ret);
  if ($cmd['limit']) {
    $t = false;
    if (is_string($cmd['limit'])) {
      $t = explode(',', $cmd['limit']);
      if (is_array($t) && count($t) === 2) {
        $t = (int) $t[0] . ',' . (int) $t[1];
      } else $t = false;
    } elseif (is_array($cmd['limit'])) {
      $t = count($cmd['limit']);
      if ($t == 1) $t = '0,' . $cmd['limit'][0];
      elseif ($t == 2) $t = (int) $cmd['limit'][0] . ',' . (int) $cmd['limit'][1];
      else $t = false;
    }
    if ($t) $ret .= ' limit ' . $t;
  }
  if ($cmd['weight']) $ret .= ' ORDER BY power DESC,changeTime DESC';
  return $ret;
};
function formatGet($val, $logic = 'and')
{
  if (!$val) return '';
  $logic = ' ' . $logic . ' ';
  $p = array_keys($val);
  $ret = '';
  $ret2 = '';
  $str = false;
  $j = 0;
  $arr = [];
  $num = count($p);
  for ($i = 0; $i < $num; $i++) {
    if ($p[$i] === 'weight' || $p[$i] === 'other') continue;
    if (is_array($val[$p[$i]])) $val[$p[$i]] = ' in(' . join($val[$p[$i]], ',') . ')';
    $ret2 = formatMysql($val[$p[$i]]);
    // $ret2 = $val[$p[$i]]; 
    $j = getRule($ret2);
    if ($p[$i] === 'limit') {
      $str = ' limit ' . $ret2;
      continue;
    }
    $ret = $p[$i];
    if ($j) {
      $ret .= ' ' . $ret2;
    } elseif (isNumber($p[$i]) || $val[$p[$i]] === 'CURRENT_TIMESTAMP' || !is_string($val[$p[$i]])) {
      $ret .= '=' . $ret2;
    } else {
      $ret .= '=\'' . $ret2 . '\'';
    }
    $arr[] = $ret;
  }

  if (isset($val['other']) && $val['other'] && strpos($val['other'], ";") === false) $str = $val['other'] . $str;

  if (isset($val['weight']) && $val['weight']) {
    $str = ' ORDER BY power DESC,changeTime DESC' . $str;
  } elseif (substr($str, 0, 1) == ',') {
    $str = ' ORDER BY ' . substr($str, 1);
  }
  if (count($arr)) {
    $ret = ' where ' . implode($logic, $arr) . $str;
  } else {
    $ret = ' where true ' . $str;
  }
  return $ret;
}
function GetData($val, $show = '*', $r0 = false, $logic = 'and', $other = '',  $retSQL = false)
{ // 失败返回假,成功以二维数组形式返回查询到的结果.
  $cmd = $val;
  if (!isset($cmd['table'])) return ['error' => '没有设置表名table', 'data' => $val];
  $tab = strtolower($cmd['table']);
  unset($cmd['table']);

  if (isset($cmd['sql'])) {
    unset($cmd['sql']);
    $retSQL = true;
  }
  global $con;
  if (!$show) $show = '*';
  $sql = 'select ';
  $sql .= $show . ' from ';
  $sql .= $tab . formatWhere($cmd, $logic) . $other;
  if ($retSQL) return $sql;
  $result = mysqli_query($con, $sql);
  if ($result === false) return ['error' => mysqli_error($con), 'data' => $val];
  $ret = mysqli_fetch_all($result, MYSQLI_ASSOC);
  mysqli_free_result($result); // 释放结果内存。
  if (!$ret) return ['error' => '当前条件下数据为空', 'data' => $sql];

  foreach ($ret as $k => $v) {
    if (is_string($v['other'])) $ret[$k]['other'] = json_decode($v['other'], true);
    if (is_string($v['items'])) $ret[$k]['items'] = json_decode($v['items'], true);
    if (is_string($v['units'])) $ret[$k]['units'] = json_decode($v['units'], true);
  }
  if ($r0 === true && $ret) {
    if (count($ret) == 1) {
      $ret = $ret[0];
      $t = array_keys($ret);
      if (count($t) == 1) $ret = $ret[$t[0]];
    } else {
      foreach ($ret as $key => $value) {
        $ret[$key] = $value['id'];
      }
    }
  }
  return $ret;
}
function noSymbol($key)
{
  $sy = ['=', '+', '-', '*', '/'];
  foreach ($sy as $v) {
    if (strpos($key, $v) > 0) return false;
  }
  return true;
}

function formatAdd($val)
{
  unset($val['id']);
  $ret = [];
  // $t = array_keys($val);
  // $ret = '(`' . implode('`,`', $t) . '`) values (';
  $t = [];
  foreach ($val as $k => $v) {
    if (!is_numeric($v) && !is_string($v)) {
      $v = formatMysql(json_encode($v, JSON_UNESCAPED_UNICODE));
    }
    if (!is_numeric($v) && !isNumber($k)) $v = "'$v'";
    $t[] = $v;
    $ret[] = $k;
  }
  $ret = '(' . implode(',', $ret) . ') values (' . implode(',', $t) . ')';
  return $ret;
}
function AddData($val, $retSQL = false)
{ // 失败返回真,成功返回假
  $cmd = $val;
  if (sureArray($cmd)) {
    $ret = [];
    foreach ($cmd as $value) {
      $ret[] = AddData($value);
    }
    return $ret;
  }
  $tab = $cmd['table'];
  unset($cmd['table']);
  $val = $cmd;
  // return $cmd;
  if ($tab == null) {
    return ['error' => 'table为空', 'data' => $val];
  }
  global $con;
  $sql = "insert into " . $tab . formatAdd($val);
  if ($retSQL) return $sql;
  // mPrintX($sql);
  $result = mysqli_query($con, $sql);
  if ($result === false) return ['error' => mysqli_error($con), 'data' => $val, 'sql' => $sql];
  $result = mysqli_query($con, 'select @@IDENTITY');
  $ret = mysqli_fetch_all($result, MYSQLI_ASSOC);
  mysqli_free_result($result); // 释放结果内存。
  $cmd['id'] = $ret[0]['@@IDENTITY'];
  if (isset($cmd['other']) && is_string($cmd['other'])) $cmd['other'] = json_decode($cmd['other'], true);
  return $cmd;
}
function formatUp($val, $cat = false)
{
  unset($val['id']);
  // $val['changeTime'] = 'CURRENT_TIMESTAMP';
  $ret = [];
  foreach ($val as $k => $v) {
    if (!is_numeric($v) && !is_string($v)) {
      $v = json_encode($v, JSON_UNESCAPED_UNICODE);
      if ($cat) $v = "='$v'";
    }
    if ($cat) {
      $v = replaceSQL($v);
    }
    $ret[] = setVal($k, $v, $cat);
  }
  return implode(',', $ret);
}
function UpData($val, $retSQL = false, $cat = false)
{ // 失败返回真,成功返回假
  $cmd = $val;
  if (sureArray($cmd)) {
    $ret = [];
    foreach ($cmd as $value) {
      $ret[] = UpData($value);
    }
    return $ret;
  }

  if (!$cmd['table'] || !$cmd['where']) return ['error' => '没有发现table/where', 'data' => $val];
  unset($cmd['token']);
  $tab = $cmd['table'];
  unset($cmd['table']);
  $where = $cmd['where'];
  unset($where['table']);
  unset($cmd['where']);
  $val = $cmd;
  if (
    $val == null
    || $tab == null
  ) {
    return ['error' => '所更改的数据为空', 'data' => $val];
  }
  global $con;
  $sql = "UPDATE " . $tab . ' set ' . formatUp($val, $cat) . formatGet($where);
  if ($retSQL) return $sql;
  $result = mysqli_query($con, $sql);
  if ($result === false) return ['error' => mysqli_error($con), 'data' => $val, 'sql' => $sql];
  if (isset($where['id'])) $cmd['id'] = $where['id'];
  return $cmd;
}
function unsetarr($arr, $uarr)
{
  $a = count($arr);
  $u = count($uarr);
  foreach ($arr as $i => $ak) {
    foreach ($uarr as $k => $v) {
      if ($i === $v) unset($arr[$i]);
    }
  }
  return $arr;
}

function runSql($sql)
{
  if (sureArray($sql)) {
    $ret = [];
    foreach ($sql as $v) {
      $t = runSql($v);
      if ($t['error']) return $t;
      $ret[] = $t;
    }
    return $ret;
  }
  global $con;
  $result = mysqli_query($con, $sql);
  $ret = false;
  if ($result) {
    if (strtolower(substr($sql, 0, 1)) == 's') {
      $ret = mysqli_fetch_all($result, MYSQLI_ASSOC); // 获取全部数据
      mysqli_free_result($result); // 释放结果内存。
    } else $ret = $result;
  } else {
    $ret = ['error' => mysqli_error($con), 'sql' => $sql];
  }
  return $ret;
}

/*
set @a=IFNULL((select max(id)from 权限),0);
INSERT INTO `tour_data`.`权限` (`名称`, `node`) VALUES ('浏览记录', 1<<@a);
insert INTO itemtype (createTime,changeTime,cuid,name,cid)VALUES(1,2,3,'维修安装',AUTO_INCREMENT);

*/
